#!/usr/bin/env python3

import os
import sys

class GCfg:
    pass

gcfg = GCfg()
gcfg.pip_source_updated = False
gcfg.defaut_pip_source = "https://pypi.tuna.tsinghua.edu.cn/simple"

def generate_pip_source(url):
    pipsrc = "[global]\n"
    pipsrc +="timeout = 6000\n"
    pipsrc +="index-url = " + url + "\n"
    pipsrc += "trusted-host = " + url.split("//")[1].split("/")[0]
    return pipsrc

def makedirs(path):
    try:
        os.makedirs(path)
    except:
        pass

def get_os_name():
    import platform
    name = platform.system()
    if name != "Linux" and name != "Windows":
        print("unsupport os:", name)
        os._exit(0)
    return name

def get_workspace_dir():
    return os.path.dirname(os.path.abspath(__file__))

def get_zvt_run():
    return os.path.join(get_workspace_dir(), "zvt_run")

def get_zvt_home():
    return os.path.join(get_zvt_run(), "zvt-home")

def get_zvt_dir():
    return os.path.join(get_workspace_dir(), "zvt_local")

def get_zvt_src():
    return os.path.join(get_zvt_dir(), "src")

def get_venv_dir():
    dirname = get_os_name() + "_venv_for_zvt"
    if get_os_name() == "Windows":
        return os.path.join(get_workspace_dir(), "zvt_run", dirname)
    else:
        return os.path.join(os.environ.get("HOME"), dirname)

def get_zvt_app():
    return os.path.join(get_workspace_dir(), "zvt_app")

def update_pip_source(url = gcfg.defaut_pip_source):
    if gcfg.pip_source_updated:
        return
    gcfg.pip_source_updated = True
    pipsrc = generate_pip_source(url)
    if get_os_name() == "Linux":
        pipdir = os.path.join(os.environ.get("HOME"), ".pip")
        makedirs(pipdir)
        with open(os.path.join(pipdir, "pip.conf"), "w+") as f:
            f.write(pipsrc)
    else:
        pipdir = os.path.join(os.environ.get("APPDATA"), "pip")
        makedirs(pipdir)
        with open(os.path.join(pipdir, "pip.ini"), "w+") as f:
            f.write(pipsrc)

def install_virtualenv():
    if get_os_name() == "Windows":
        update_pip_source()
        os.system("python -m pip install virtualenv")
    else:
        os.system("sudo apt -y install python3-virtualenv")

def make_venv():
    os.system('virtualenv -p "' + sys.executable + '" "' + get_venv_dir() + '"')

def do_func(invoker):
    invoker = globals()[invoker]
    invoker()
    os._exit(0)

def is_in_venv():
    venv = os.environ.get("VIRTUAL_ENV")
    if venv == None:
        return False
    vdir = os.path.realpath(get_venv_dir())
    envv = os.path.realpath(os.environ.get("VIRTUAL_ENV"))
    if get_os_name() == "Windows":
        vdir = vdir.upper()
        envv = envv.upper()
    return vdir == envv

def use_zvt_src():
    if sys.path[0] == "":
        del sys.path[0]
    sys.path.insert(0, get_workspace_dir())
    sys.path.insert(0, get_zvt_dir())
    sys.path.insert(0, get_zvt_src())
    
def on_run_cmd(name):
    use_zvt_src()
    do_func(name)

def enter_venv(invoker):
    if is_in_venv():
        on_run_cmd(invoker) 
    if get_os_name() == "Windows":
        cmd = 'cd "' + get_venv_dir() + r'\Scripts" & activate & cd "' + get_workspace_dir() + '" & '
        cmd = cmd + ' "' + get_venv_dir() + r'\Scripts\python.exe' + '" "' + __file__ + '" ' + invoker
        os.system(cmd)
    else:
        cmd = 'cd "' + get_venv_dir() + '/bin" ; source activate ; cd "' + get_workspace_dir() + '" ; '        
        cmd = cmd + ' "' + get_venv_dir() + '/bin/python3" "' + __file__ + '" ' + invoker
        cmd_sh = os.path.join(os.environ.get("HOME"), "venv_cmd")
        f = open(cmd_sh, "w+")
        f.write(cmd)
        f.close()
        os.system('/bin/bash "' + cmd_sh + '"')
    os._exit(0)

def read_requirements(fn, reqs = None):
    if reqs is None:
        reqs = {}
    with open(fn) as f:
        for req in f.readlines():
            req = req.strip()
            if req == "":
                continue            
            if "==" in req:
                parts = req.split("==")
                reqd = {"pkg":parts[0].strip(), "cond": "==", "ver": parts[1].strip()}
            elif ">=" in req:
                parts = req.split(">=")
                reqd = {"pkg":parts[0].strip(), "cond": ">=", "ver": parts[1].strip()}
            elif ">" in req:
                parts = req.split(">")
                reqd = {"pkg":parts[0].strip(), "cond": ">", "ver": parts[1].strip()}
            else:
                reqd = {"pkg":req.strip(), "cond": "", "ver": ""}
            reqs[reqd["pkg"]] = reqd
    return reqs

def do_init():
    update_pip_source()
    if get_os_name() == "Windows":
        pipcmd = "pip"
    else:
        pipcmd = "pip3"
    reqs = read_requirements(os.path.join(get_zvt_dir(), "requirements.txt"))
    strict_pkg = ["SQLAlchemy", "dash", "dash-bootstrap-components", "dash_daq", "Werkzeug"]
    for pkg in reqs:
        if pkg not in reqs.keys():
            if "==" == reqs[pkg]["cond"]:
                 reqs[pkg]["cond"] = ">="
    reqs = read_requirements(os.path.join(get_zvt_app(), "requirements.txt"), reqs)
    newreqf = os.path.join(get_zvt_run(), "requirements.txt")
    with open(newreqf, "w+") as f:
        for pkg in reqs:
            f.write(pkg + reqs[pkg]["cond"] + reqs[pkg]["ver"] + "\n")
    os.system(pipcmd + " install -r " + newreqf)


def init():
    os.environ["ZVT_HOME"] = get_zvt_home()
    makedirs(os.path.join(get_zvt_home(), "data"))
    makedirs(os.path.join(get_zvt_home(), "logs"))
    makedirs(os.path.join(get_zvt_home(), "tmp"))
    makedirs(os.path.join(get_zvt_home(), "ui"))
    install_virtualenv()
    make_venv()
    enter_venv("do_init")

os.environ["ZVT_HOME"] = get_zvt_home()

def dldata():
    use_zvt_src()
    import zvt_app.dldata

def test():
    use_zvt_src()
    import zvt_app.test

def main():
    use_zvt_src()    
    import zvt_app.main

if len(sys.argv) > 1:
    if sys.argv[1] == "init":
        do_func(sys.argv[1])
    else:
        enter_venv(sys.argv[1])
else:
    enter_venv("main")

